﻿///<FileHeader>
///     <FileName>TypeDescriptionProvider.cs</FileName>
///     <Author>Kiran Chand Palakkattiri</Author>
///     <Project>
///         <Name>Property Visibility Extensions for DSL</Name>
///         <Url>http://kiranchand.codeplex.com</Url>
///     </Project>
///     <CreationDate>August 02, 2009.</CreationDate>
///     <Contents>
///         <Content type="class" name="ModelTypeDescriptionProvider"
///             baseclass="ElementTypeDescriptionProvider"
///             comments="Type description provider for DSL model elements."/>
///     </Contents>
///     <Dependencies>
///         <Dependency type="reference" namespace="System" />
///         <Dependency type="reference" namespace="System.Collections.Generic" />
///         <Dependency type="reference" namespace="System.ComponentModel" />
///         <Dependency type="reference" namespace="System.Reflection" />
///         <Dependency type="reference" namespace="Microsoft.VisualStudio.Modeling"
///             assembly="Microsoft.VisualStudio.Modeling.Sdk" version="9.0.0.0" prerequisites="Visual Studio SDK 1.1"/>
///         <Dependency type="reference" namespace="Microsoft.VisualStudio.Modeling.Design"
///             assembly="Microsoft.VisualStudio.Modeling.Sdk" version="9.0.0.0" prerequisites="Visual Studio SDK 1.1" />
///     </Dependencies>
///     <Modifications>
///         <Modification changeset="1002" date="August 09, 2009" author="Kiran Chand Palakkattiri">
///             <Target="function" targetname="RegisterProvider(Type type)" type="update"
///                 comment="promoted the access specifier from private to public"/>
///             <Target="function" targetname="RegisterProvider(Type type)" type="update"
///                 comment="included the type check during registering provider; model elements alone are allowed"/>
///         </Modification>
///         <Modification changeset="1005" date="August 30, 2009" author="Kiran Chand Palakkattiri">
///             <Target="function" targetname="RegisterProvider(Type type)" type="update"
///                 comment="included the patches for new type descriptor"/>
///             <Target="function" targetname="RegisterProvider(Type type)" type="update"
///                 comment="removed the attribute count check to separate function"/>
///             <Target="function" targetname="CreateTypeDescriptor(...)" type="update"
///                 comment="Added support for the new decorator based advanced type descriptor; added code for supporting caching"/>
///             <Target="function" targetname="HasBehaviorAttributes(Type type)" type="create"
///                 comment="checks whether the given type has property behavior attributes defined or not."/>
///             <Target="function" targetname="IsPropertyDecorator(Type type)" type="create"
///                 comment="checks whether the given type implements the IPropertyVisibilityDecorator interface or not."/>
///             <Target="property" targetname="TypeDescriptorCache" type="create"
///                 comment="added dictionary supporting caching"/>
///             <Target="constructor" targetname="ModelTypeDescriptionProvider()" type="update"
///                 comment="added the code supporting caching"/>
///         </Modification>
///         <Modification changeset="1004" date="September 01, 2009" author="Kiran Chand Palakkattiri">
///             <Target="property" targetname="TypeDescriptorCache" type="delete"
///                 comment="unable to manage the state of the cache. cached standardValueProvider becomes null in the type descriptor"/>
///             <Target="constructor" targetname="ModelTypeDescriptionProvider()" type="update"
///                 comment="removed the code supporting caching"/>
///             <Target="function" targetname="CreateTypeDescriptor(...)" type="update"
///                 comment="removed code for supporting caching"/>
///         </Modification>
///         <Modification changeset="1005" date="September 08, 2009" author="Kiran Chand Palakkattiri">
///             <Target="function" targetname="CreateTypeDescriptor" type="update"
///                 comment="added the support for the role player interfaces"/>
///         </Modification>
///     </Modifications>
///     <Version>5.0.0.0</Version>
///</FileHeader>

using System;
using System.ComponentModel;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Design;

namespace Kiranchand.Dsl.Extensions.PropertyVisibility
{
    /// <summary>
    /// Type description provider for DSL model elements.
    /// </summary>
    public class ModelElementDescriptionProvider : ElementTypeDescriptionProvider
    {
        /// <summary>
        /// Initializes the type description provider
        /// </summary>
        public ModelElementDescriptionProvider()
            : base()
        {

        }
        /// <summary>
        /// Creates the instance of model type descriptor instance.
        /// </summary>
        /// <param name="parent">the instance of the parent type descriptor.
        /// It has absolutely no role with property behavior.
        /// feel free to use null</param>
        /// <param name="element">the instance of the model standardValueProvider. this should not be null</param>
        /// <returns>new instance of the model type descriptor.</returns>
        /// <exception cref=""></exception>
        protected override ElementTypeDescriptor CreateTypeDescriptor(ICustomTypeDescriptor parent
            , ModelElement element)
        {
            ElementTypeDescriptor descriptor = null;       // holds the standardValueProvider type descriptor instance

            // Element Null? Raise the exception
            if (element == null)
                throw new ArgumentNullException("element", "The model element instance should not be null");
            // check whether the model standardValueProvider is a property visibility decorator or role player provider
            else if (ModelElementDescriptionProvider.IsPropertyDecorator(element.GetType()))
                descriptor = new ModelElementDescriptor(element);
            // oh! no! My dear DSL; its your turn! we are here for default settings
            else
                descriptor = base.CreateTypeDescriptor(parent, element);
            return descriptor;
        }


        /// <summary>
        /// Checks whether the given type implements the IPropertyVisibilityDecorator interface or not
        /// </summary>
        /// <param name="type">the type of the instance</param>
        /// <returns>a boolean denoting whether the given type implements the
        /// IPropertyVisibilityDecorator interface or not</returns>
        private static bool IsPropertyDecorator(Type type)
        {
            bool bIsPropertyDecorator = false;  // holds the status.

            // get the type of all the interfaces that current type implements
            Type[] interfaces = type.GetInterfaces();

            // check the count
            if (interfaces != null && interfaces.Length > 0)
            {
                // iterate through the interfaces
                foreach (Type interfaceType in interfaces)
                {
                    // check whether it is IPropertyVisibilityDecorator
                    if (interfaceType.Equals(typeof(IPropertyVisibilityDecorator))
                        || interfaceType.Equals(typeof(IRolePlayerVisibilityDecorator))
                        || interfaceType.Equals(typeof(IRolePlayerProviderDecorator)))
                    {
                        // set status and break
                        bIsPropertyDecorator = true;
                        break;
                    }
                }
            }

            // clean up
            interfaces = null;

            // return
            return bIsPropertyDecorator;
        }
    }
}
